﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Apollo.Core;
using Apollo.Web;
using Apollo;

namespace Apollo.Website
{
    public partial class Controls_Edit_FormGroup : System.Web.UI.UserControl
    {
        public FormGroup Group { get; set; }

        public object TargetObject { get; set; }

        public IList<IFormItem> formItems = new List<IFormItem>();

        protected void Page_Load(object sender, EventArgs e)
        {
            switch (this.Group.Type)
            {
                case FormGroupType.Properties:
                    PlaceHolderMain.Controls.Add(new LiteralControl("<h3>" + this.Group.DisplayName + "</h3>"));

                    Table table = new Table(this.Group);

                    if (table.Rows.Count < 1 || table.Rows[0].Cells.Count < 1) {
                        PlaceHolderMain.Controls.Add(new LiteralControl("<!-- Nothing to see boys! Move along! -->"));
                        break;
                    }

                    
                    PlaceHolderMain.Controls.Add(new LiteralControl("<table cellpadding=3 cellspacing=0 border=0 width=100%>"));
                    foreach (TableRow row in table.Rows) {
                        PlaceHolderMain.Controls.Add(new LiteralControl("<tr>"));

                        foreach (TableCell cell in row.Cells) {
                            if(cell.BelongsTo != null)
                                continue;

                            string td_definition = "";
                            if (cell.FormItem != null)
                            {
                                if (cell.FormItem.ColSpan > 1) 
                                    td_definition += " colspan=\"" + cell.FormItem.ColSpan.ToString() + "\"";
                                if (cell.FormItem.RowSpan > 1) 
                                    td_definition += " rowspan=\"" + cell.FormItem.RowSpan.ToString() + "\"";
                            }
                            
                            PlaceHolderMain.Controls.Add(new LiteralControl("<td"+td_definition+">"));

                            if (cell.FormItem != null)
                            {
                                Controls_Edit_FormItem fiControl = this.LoadControl("~/Controls/Edit/FormItem.ascx") as Controls_Edit_FormItem;
                                fiControl.Item = cell.FormItem;
                                fiControl.TargetObject = this.TargetObject;

                                if (fiControl.Item.Projection.IsReadOnly)
                                    fiControl.Item.Type = FormItemType.ReadOnly;

                                formItems.Add(fiControl);

                                PlaceHolderMain.Controls.Add(fiControl);
                            }
                            else {
                                PlaceHolderMain.Controls.Add(new LiteralControl("&nbsp;"));
                            }

                            if (!string.IsNullOrEmpty(cell.Comment))
                                PlaceHolderMain.Controls.Add(new LiteralControl("<i> " + cell.Comment + " </i>"));

                            PlaceHolderMain.Controls.Add(new LiteralControl("</td>"));
                        }

                        PlaceHolderMain.Controls.Add(new LiteralControl("</tr>"));
                    }
                    PlaceHolderMain.Controls.Add(new LiteralControl("</table>"));

                    break;

                case FormGroupType.Tab:
                    foreach (FormGroup subgroup in this.Group.SubGroups)
                    {
                        Controls_Edit_FormGroup sgControl = this.LoadControl("~/Controls/Edit/FormGroup.ascx") as Controls_Edit_FormGroup;
                        sgControl.Group = subgroup;
                        sgControl.TargetObject = this.TargetObject;
                        PlaceHolderMain.Controls.Add(sgControl);
                    }

                    break;
            }
        }

        public ActionContext Save(object obj)
        {
            ActionContext context = new ActionContext();

            foreach (IFormItem formItem in this.formItems)
            {
                ActionMessage msg = formItem.Save(obj);

                if (msg != null)
                    context.AddMessage(msg);
            }

            return context;
        }

        public class Table
        {
            public IList<TableRow> Rows { get; private set; }

            public TableCell this[int row, int cell] {
                get { return this.Rows[row].Cells[cell]; }
            }


            public Table(FormGroup group)
            {
                this.Rows = new List<TableRow>();

                // Col and Row should be zero-based
                foreach (FormItem item in group.Items) {
                    this.AddRowsUntil(item.Row + item.RowSpan);
                    this.AddColsUntil(item.Col + item.ColSpan);

                    this.SetBelongToFormItem(item);
                }
            }

            private void AddColsUntil(int numberOfCols) {
                if(numberOfCols <= 0) 
                    return;

                foreach (TableRow r in this.Rows) {
                    while (r.Cells.Count < numberOfCols)
                    r.Cells.Add(new TableCell());
                }
            }

            private void AddRowsUntil(int numberOfRows) {
                int numberOfCells = 0;
                if(this.Rows.Count > 0 && this.Rows[0].Cells != null)
                    numberOfCells = this.Rows[0].Cells.Count;

                while (this.Rows.Count < numberOfRows) {
                    TableRow r = new TableRow();

                    for (int i = 0; i < numberOfCells; i++)
                        r.Cells.Add(new TableCell());

                    this.Rows.Add(r);
                }
            }

            private void SetBelongToFormItem(FormItem item) {
                TableCell parent = this[item.Row, item.Col];

                if (parent.FormItem != null) {
                    parent.Comment = "Multiple form items defined for this cell. <b>" 
                        + item.Projection.DisplayName + "</b> was ignored!";
                    return;
                }

                if (parent.BelongsTo != null) {
                    parent.BelongsTo.Comment = "This overrides <b>" + item.Projection.DisplayName + "</b>";
                    return;
                }

                parent.FormItem = item;


                if (item.ColSpan > 1) {
                    for (int i = 1; i < item.ColSpan; i++) {
                        TableCell child = this[item.Row, item.Col + i];

                        if (child.FormItem != null || child.BelongsTo != null)
                        {
                            parent.Comment = "Colspan reduced from " + item.ColSpan.ToString() + " to " + i.ToString();
                            item.ColSpan = i;
                        }
                        else {
                            child.BelongsTo = parent;
                        }
                    }
                }

                if (item.RowSpan > 1) {
                    for (int j = 1; j < item.RowSpan; j++)
                    {
                        TableCell child = this[item.Row + j, item.Col];

                        if (child.FormItem != null || child.BelongsTo != null)
                        {
                            parent.Comment = "Rowspan reduced from " + item.RowSpan.ToString() + " to " + j.ToString();
                            item.RowSpan = j;
                        }
                        else
                        {
                            child.BelongsTo = parent;
                        }
                    }
                }
            }

        }


        public class TableRow
        {
            public TableRow() { this.Cells = new List<TableCell>(); }

            public IList<TableCell> Cells { get; set; }
        }

        public class TableCell
        {
            public TableCell() { }

            public TableCell BelongsTo { get; set; }

            public FormItem FormItem { get; set; }

            public string Comment { get; set; }
        }
    }
}